0. 前言
上回介紹的了RISC-V Hart的Debug支援的部分,有稍微提到一個東西!
所以今天來聊聊Debug System中另一個重要的功能--Trigger Module
突然發現或許是標題或是內文太生硬,點閱人數可能不太多~!
應該來個聳動一點的標題騙騙點閱率XD!
1. Overview
簡單的說,Trigger Module的主要作用就是用來觸發"Breakpoint exception",並立即進入Debug Mode中,或是用來追蹤(Trace)程式執行的過程~!
主要功用如下:
- 在指定的位置下Breakpoint,當該行指令被執行時觸發
- 在指定的位置下Watchpoint,當程式去讀/寫那個位置時觸發
2. Trigger Registers Detailed
為了避免未經OS授權的User Code透過Trigger進入Debug Mode,因此以下所有的Trigger Registers都只能夠在M(machine) Mode和Debug Mode中才能夠被讀/寫!
底下挑選幾個來說明:
- 0x7a0 tselect: Trigger Select
- 0x7a1 tdata1: Trigger Data 1,依照type還可以再細分成以下兩種格式
- mcontrol: Match Control
- icount: Instruction Count
- 0x7a2 tdata2: Trigger Data 2
2.1 0x7a0 tselect: Trigger Select
透過$tselect來選擇目前作用的Trigger,後面的$tdata1、$tdata2、$tdata3則會依照這個編號,選擇對應的Register來寫入!
---引用自RISC-V External Debug Support 0.13
只有一個欄位:
另外有些規則需要特別注意:
- 所有的編號都是從0開始,連續的編號下去
- 由於未必保證該編號的Trigger存在,因此Debugger在使用時,務必做好確認
- 確認方法也很簡單,就是把$tselect再讀一次回來,確認跟寫入相同時就表示存在!
- 由於Trigger在M(Machine) Mode中也可以被使用到,Debugger務必先做好備份
- 在離開Debug Mode時候,把備份好的值還原回去!
2.2 0x7a1 tdata1: Trigger Data 1
---引用自RISC-V External Debug Support 0.13
主要的欄位如下:
- type: 該Trigger的種類,可以分類如下
- 0: 該Trigger編號的不存在
- 1: SiFive自己的"address match trigger",不在本文的討論範圍內
- 2: 當作"Address Match Trigger"用,詳細內容請參考下方"2.2.1 mcontrol: Match Control"
- 3: 當作"Instruction Count Trigger"用,詳細內容請參考下方"2.2.2 icount: Instruction Count"
- 15: 該Trigger存在,但目前不可用!
- dmode: 用來設定該Trigger在M(Machine) Mode中是否可以被寫入
- 0: M(Machine) Mode中也可以被使用
- 1: 只有Debug Mode中才可以寫入該Trigger
- data: 詳細的細節請參考下方"2.2.1 mcontrol: Match Control"和"2.2.2 icount: Instruction Count"中的意義
2.2.1 mcontrol: Match Control (type = 2)
Trigger在此主要當作 Breakpoint(Address Match Trigger) / Watchpoint(Data Match Trigger) 使用,type跟dmode前面敘述過了,底下說明data中各個欄位的意義!
另外在使用這個mcontrol的時候,同時也會用到$tdata2來存放資料,詳情請看底下"2.3 0x7a2 tdata2: Trigger Data 2"的說明
---引用自RISC-V External Debug Support 0.13
- maskmax: 跟硬體設計有關,用來標示Trigger能夠比較的範圍!? (這個我也不知道是啥用途的)
- select: 用來標示要比較的資料
- 0: Virtual Address
- 1: Data Value(Watchpoint)、Instruction Executed(Breakpoint)
- timing: 主要用來標示Trigger發生的點是在該行指令執行的前/後,端看硬體的設計 (*註1)
- action: 用來標示Trigger在Match後需要執行的動作
- 0: "Breakpoint Exception"
- 1: 進入Debug Mode
- 2: 開始Tracing
- 3: 停止Tracing
- 4: Tracing用,記錄當下的Address/Data/PC等等
- chain: 這個我也不知道是啥用途的
- match: 用來標示資料比較的方式,讓Debugger設計上能夠更加彈性
- 0: 比較的值必須要剛好等同於$tdata2的值
- 1: 只比較$tdata2中前M個Bits的值
- 2: 當資料的值"大於等於"$tdata2的值
- 3: 當資料的值"小於"$tdata2的值
- 4: 有看沒懂,留給其他厲害的高手回答 囧
- 5: 有看沒懂,留給其他厲害的高手回答 囧
- m: 用來表示這個Trigger是否可以在M(machine) Mode中啟動
- h: 用來表示這個Trigger是否可以在H(hypervisor) Mode中啟動
- s: 用來表示這個Trigger是否可以在S(supervisor) Mode中啟動
- execute: 給Breakpoint用,用來表示在該行指令執行時啟動
- store: 給Watchpoint用,用來表示在該Data被儲存時啟動
- load: 給Watchpoint用,用來表示在該Data被讀取時啟動
(*註1): 底下列出文件中建議的Timing
---引用自RISC-V External Debug Support 0.13
2.2.2 icount: Instruction Count (type = 3)
這個Trigger是當成"計步器"用,隨著程式的執行,依據條件不斷的"-1",直到變成0為止,才停下來,做預先設定好的動作,是不是很像硬體的計步器啊!!
---引用自RISC-V External Debug Support 0.13
- count: 用來標示倒數的值
- m: 在M(machine) Mode執行每行指令,自動"-1"
- h: 在H(hypervisor) Mode執行每行指令,自動"-1"
- s: 在S(supervisor) Mode執行每行指令,自動"-1"
- u: 在U(user) Mode執行每行指令,自動"-1"
- action: 同上面"# 2.2.1 mcontrol: Match Control"的內容,這邊不多加贅述
不過要先說下,目前沒看到這部分有實作出來~~~
2.3 0x7a2 tdata2: Trigger Data 2
---引用自RISC-V External Debug Support 0.13
當tdata1的type為2(mcontrol)的時候,這個Register就變成存放比較的資料用!
99. 結語
簡單的介紹完整個Trigger Module的架構和所需要的Register!
不過呢! 周末是想耍廢! 我們還是等到明天再來看看實作的程式碼吧!!
參考資料
-
RISC-V External Debug Support 0.13
-
GitHub: riscv/riscv-openocd